<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>箭头函数练习题</title>
    <style>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            line-height: 1.6;
            margin: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        h1 {
            color: #333;
            text-align: center;
            border-bottom: 3px solid #007acc;
            padding-bottom: 10px;
        }
        h2 {
            color: #007acc;
            margin-top: 30px;
            border-left: 4px solid #007acc;
            padding-left: 15px;
        }
        .exercise {
            background: #f8f9fa;
            border: 1px solid #e9ecef;
            border-radius: 8px;
            padding: 20px;
            margin: 15px 0;
        }
        .exercise h3 {
            color: #495057;
            margin-top: 0;
        }
        .question {
            background: #fff3cd;
            border: 1px solid #ffeaa7;
            border-radius: 5px;
            padding: 15px;
            margin: 10px 0;
        }
        .answer {
            background: #d1ecf1;
            border: 1px solid #bee5eb;
            border-radius: 5px;
            padding: 15px;
            margin: 10px 0;
            display: none;
        }
        .answer.show {
            display: block;
        }
        .toggle-btn {
            background: #007acc;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            margin: 10px 0;
        }
        .toggle-btn:hover {
            background: #0056b3;
        }
        code {
            background: #f1f3f4;
            padding: 2px 6px;
            border-radius: 3px;
            font-family: 'Consolas', 'Monaco', monospace;
        }
        pre {
            background: #f8f9fa;
            border: 1px solid #e9ecef;
            border-radius: 5px;
            padding: 15px;
            overflow-x: auto;
        }
        .difficulty {
            display: inline-block;
            padding: 4px 8px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: bold;
            margin-left: 10px;
        }
        .easy { background: #d4edda; color: #155724; }
        .medium { background: #fff3cd; color: #856404; }
        .hard { background: #f8d7da; color: #721c24; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎯 箭头函数练习题</h1>
        
        <h2>📚 基础练习</h2>
        
        <div class="exercise">
            <h3>练习1：基本箭头函数转换 <span class="difficulty easy">简单</span></h3>
            <div class="question">
                <p>将以下传统函数转换为箭头函数：</p>
                <pre><code>function add(a, b) {
    return a + b;
}</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer1')">显示答案</button>
                <div id="answer1" class="answer">
                    <pre><code>const add = (a, b) => a + b;</code></pre>
                    <p><strong>解释：</strong>当函数体只有一行且是return语句时，可以省略大括号和return关键字。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习2：单参数箭头函数 <span class="difficulty easy">简单</span></h3>
            <div class="question">
                <p>将以下函数转换为箭头函数：</p>
                <pre><code>function square(x) {
    return x * x;
}</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer2')">显示答案</button>
                <div id="answer2" class="answer">
                    <pre><code>const square = x => x * x;</code></pre>
                    <p><strong>解释：</strong>当只有一个参数时，可以省略参数周围的括号。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习3：无参数箭头函数 <span class="difficulty easy">简单</span></h3>
            <div class="question">
                <p>将以下函数转换为箭头函数：</p>
                <pre><code>function getCurrentTime() {
    return new Date();
}</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer3')">显示答案</button>
                <div id="answer3" class="answer">
                    <pre><code>const getCurrentTime = () => new Date();</code></pre>
                    <p><strong>解释：</strong>无参数时，必须使用空括号 <code>()</code>。</p>
                </div>
            </div>
        </div>

        <h2>🔧 中级练习</h2>

        <div class="exercise">
            <h3>练习4：数组方法中的箭头函数 <span class="difficulty medium">中等</span></h3>
            <div class="question">
                <p>使用箭头函数重写以下代码：</p>
                <pre><code>const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function(num) {
    return num * 2;
});</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer4')">显示答案</button>
                <div id="answer4" class="answer">
                    <pre><code>const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);</code></pre>
                    <p><strong>解释：</strong>箭头函数在数组方法中非常简洁，常用于map、filter、reduce等。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习5：多行箭头函数 <span class="difficulty medium">中等</span></h3>
            <div class="question">
                <p>将以下函数转换为箭头函数：</p>
                <pre><code>function processUser(user) {
    if (user.age >= 18) {
        return user.name + ' 是成年人';
    } else {
        return user.name + ' 是未成年人';
    }
}</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer5')">显示答案</button>
                <div id="answer5" class="answer">
                    <pre><code>const processUser = user => {
    if (user.age >= 18) {
        return user.name + ' 是成年人';
    } else {
        return user.name + ' 是未成年人';
    }
};</code></pre>
                    <p><strong>解释：</strong>多行函数体时，必须使用大括号和return语句。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习6：箭头函数与this绑定 <span class="difficulty medium">中等</span></h3>
            <div class="question">
                <p>分析以下代码的输出结果：</p>
                <pre><code>const obj = {
    name: '张三',
    traditional: function() {
        console.log('传统函数:', this.name);
    },
    arrow: () => {
        console.log('箭头函数:', this.name);
    }
};

obj.traditional();
obj.arrow();</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer6')">显示答案</button>
                <div id="answer6" class="answer">
                    <pre><code>// 输出结果：
// 传统函数: 张三
// 箭头函数: undefined</code></pre>
                    <p><strong>解释：</strong>箭头函数不绑定自己的this，它会继承外层作用域的this。在这个例子中，箭头函数的this指向全局对象。</p>
                </div>
            </div>
        </div>

        <h2>🚀 高级练习</h2>

        <div class="exercise">
            <h3>练习7：链式调用与箭头函数 <span class="difficulty hard">困难</span></h3>
            <div class="question">
                <p>使用箭头函数重写以下代码，实现数组的链式操作：</p>
                <pre><code>const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 传统写法
const result = numbers
    .filter(function(num) {
        return num % 2 === 0;
    })
    .map(function(num) {
        return num * num;
    })
    .reduce(function(sum, num) {
        return sum + num;
    }, 0);</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer7')">显示答案</button>
                <div id="answer7" class="answer">
                    <pre><code>const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const result = numbers
    .filter(num => num % 2 === 0)
    .map(num => num * num)
    .reduce((sum, num) => sum + num, 0);

console.log(result); // 输出: 220</code></pre>
                    <p><strong>解释：</strong>箭头函数让链式调用更加简洁易读。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习8：箭头函数作为回调 <span class="difficulty hard">困难</span></h3>
            <div class="question">
                <p>创建一个函数，使用箭头函数处理异步操作：</p>
                <pre><code>// 要求：创建一个函数，接收一个数字数组，返回每个数字的平方
// 使用setTimeout模拟异步操作，延迟100ms后返回结果
// 使用箭头函数和Promise</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer8')">显示答案</button>
                <div id="answer8" class="answer">
                    <pre><code>const asyncSquare = numbers => {
    return Promise.all(
        numbers.map(num => 
            new Promise(resolve => 
                setTimeout(() => resolve(num * num), 100)
            )
        )
    );
};

// 使用示例
asyncSquare([1, 2, 3, 4, 5])
    .then(results => console.log(results)) // [1, 4, 9, 16, 25]
    .catch(error => console.error(error));</code></pre>
                    <p><strong>解释：</strong>箭头函数在异步编程中非常有用，特别是在Promise和async/await中。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习9：箭头函数的this陷阱 <span class="difficulty hard">困难</span></h3>
            <div class="question">
                <p>分析以下代码，找出问题并修复：</p>
                <pre><code>const calculator = {
    value: 0,
    add: function(num) {
        this.value += num;
        return this;
    },
    multiply: function(num) {
        this.value *= num;
        return this;
    },
    getValue: () => {
        return this.value;
    }
};

calculator.add(5).multiply(2);
console.log(calculator.getValue()); // 期望输出: 10</code></pre>
                <button class="toggle-btn" onclick="toggleAnswer('answer9')">显示答案</button>
                <div id="answer9" class="answer">
                    <pre><code>// 问题：箭头函数的this不会指向calculator对象
// 修复方案1：使用传统函数
const calculator = {
    value: 0,
    add: function(num) {
        this.value += num;
        return this;
    },
    multiply: function(num) {
        this.value *= num;
        return this;
    },
    getValue: function() {
        return this.value;
    }
};

// 修复方案2：使用箭头函数但绑定this
const calculator2 = {
    value: 0,
    add: function(num) {
        this.value += num;
        return this;
    },
    multiply: function(num) {
        this.value *= num;
        return this;
    },
    getValue: function() {
        return this.value;
    }
};</code></pre>
                    <p><strong>解释：</strong>箭头函数不绑定this，在对象方法中使用时要特别注意。</p>
                </div>
            </div>
        </div>

        <div class="exercise">
            <h3>练习10：综合应用 <span class="difficulty hard">困难</span></h3>
            <div class="question">
                <p>创建一个学生管理系统，使用箭头函数实现以下功能：</p>
                <ul>
                    <li>添加学生</li>
                    <li>根据年龄筛选学生</li>
                    <li>计算平均成绩</li>
                    <li>找出成绩最高的学生</li>
                </ul>
                <button class="toggle-btn" onclick="toggleAnswer('answer10')">显示答案</button>
                <div id="answer10" class="answer">
                    <pre><code>class StudentManager {
    constructor() {
        this.students = [];
    }
    
    addStudent = (name, age, score) => {
        this.students.push({ name, age, score });
    }
    
    filterByAge = minAge => 
        this.students.filter(student => student.age >= minAge)
    
    getAverageScore = () => 
        this.students.reduce((sum, student) => sum + student.score, 0) / this.students.length
    
    getTopStudent = () => 
        this.students.reduce((top, current) => 
            current.score > top.score ? current : top
        )
    
    getStudentsInfo = () => 
        this.students.map(student => 
            `${student.name}(${student.age}岁): ${student.score}分`
        )
}

// 使用示例
const manager = new StudentManager();
manager.addStudent('张三', 20, 85);
manager.addStudent('李四', 19, 92);
manager.addStudent('王五', 21, 78);

console.log('所有学生:', manager.getStudentsInfo());
console.log('20岁以上学生:', manager.filterByAge(20));
console.log('平均成绩:', manager.getAverageScore());
console.log('最高分学生:', manager.getTopStudent());</code></pre>
                    <p><strong>解释：</strong>这个例子展示了箭头函数在类方法、数组操作和对象处理中的综合应用。</p>
                </div>
            </div>
        </div>

        <h2>💡 总结</h2>
        <div class="exercise">
            <h3>箭头函数使用要点</h3>
            <ul>
                <li><strong>语法简洁：</strong>单行函数可以省略大括号和return</li>
                <li><strong>this绑定：</strong>箭头函数不绑定自己的this，继承外层作用域</li>
                <li><strong>不能作为构造函数：</strong>箭头函数没有prototype属性</li>
                <li><strong>没有arguments对象：</strong>使用rest参数(...args)代替</li>
                <li><strong>适合回调函数：</strong>在数组方法、Promise等场景中非常有用</li>
            </ul>
        </div>
    </div>

    <script>
        function toggleAnswer(answerId) {
            const answer = document.getElementById(answerId);
            answer.classList.toggle('show');
        }

        // 运行一些示例代码
        console.log('=== 箭头函数练习示例 ===');
        
        // 练习1示例
        const add = (a, b) => a + b;
        console.log('add(3, 4):', add(3, 4));
        
        // 练习4示例
        const numbers = [1, 2, 3, 4, 5];
        const doubled = numbers.map(num => num * 2);
        console.log('原数组:', numbers);
        console.log('翻倍后:', doubled);
        
        // 练习7示例
        const result = numbers
            .filter(num => num % 2 === 0)
            .map(num => num * num)
            .reduce((sum, num) => sum + num, 0);
        console.log('偶数平方和:', result);
    </script>
</body>
</html>
